package sys_serv

import (
	"strconv"
	"strings"
	"ubt-rbac-service/internal/app/model"
	"ubt-rbac-service/internal/app/model/sys_mod"
	"ubt-rbac-service/internal/app/util"
	"ubt-rbac-service/internal/core/logger"
)

type sysType struct{}

var SysTypeServ = sysType{}

// Add 新增分类
func (s *sysType) Add(req *sys_mod.SysTypeSaveReq) *model.Result {
	sqlStr := "INSERT INTO sys_type(type_name, type_code, short_name, full_name, quan_pin, jian_pin, kind, parent_id, sort, " +
		"logo_id, logo_name, logo_url, remarks, states, add_time, opt_org) " +
		"VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, 1, EXTRACT(EPOCH FROM NOW()), $14)"
	retCode, retMsg := util.CudData(sqlStr, req.TypeName, req.TypeCode, req.ShortName, req.FullName, req.QuanPin, req.JianPin,
		req.Kind, req.ParentId, req.Sort, req.LogoId, req.LogoName, req.LogoUrl, req.Remarks, req.OptOrg)
	return &model.Result{RetCode: retCode, RetMsg: retMsg}
}

// Exists 判断平台编码是否存在
func (s *sysType) Exists(req *sys_mod.SysTypeExtVo) bool {
	sqlStr := "SELECT COUNT(1) AS nums FROM sys_type WHERE states=1 AND opt_org=$1 AND kind=$2 AND (type_name=$3 OR type_code=$4)"
	param := make([]interface{}, 0)
	param = append(param, req.OptOrg)
	param = append(param, req.Kind)
	param = append(param, req.TypeName)
	param = append(param, req.TypeCode)
	if req.TypeId != "" {
		sqlStr += " AND type_id!=$5"
		param = append(param, req.TypeId)
	}
	if dbMap, err := util.GetOne(sqlStr, param...); err == nil && len(dbMap) > 0 {
		if dbMap["nums"].(int64) > 0 {
			return true
		}
	}
	return false
}

// Update 修改分类
func (s *sysType) Update(req *sys_mod.SysTypeSaveReq) *model.Result {
	sqlStr := "UPDATE sys_type SET type_name=$1, type_code=$2, short_name=$3, full_name=$4, quan_pin=$5, jian_pin=$6, " +
		"kind=$7, parent_id=$8, sort=$9, logo_id=$10, logo_name=$11, logo_url=$12, remarks=$13, upd_time=EXTRACT(EPOCH FROM NOW()) " +
		"WHERE type_id=$14"
	retCode, retMsg := util.CudData(sqlStr, req.TypeName, req.TypeCode, req.ShortName, req.FullName, req.QuanPin, req.JianPin,
		req.Kind, req.ParentId, req.Sort, req.LogoId, req.LogoName, req.LogoUrl, req.Remarks, req.TypeId)
	return &model.Result{RetCode: retCode, RetMsg: retMsg}
}

// Deletes 删除分类
func (s *sysType) Deletes(req *sys_mod.SysTypeProReq) *model.Result {
	var (
		param  []interface{}
		idList []string
		q      string
		n      = 0
	)
	idArr := strings.Split(req.TypeIds, ",")
	modList := s.selTypes(req)
	for _, curId := range idArr {
		idList = append(idList, curId)
		idList = s.getIds(modList, curId, idList)
	}
	for _, curId := range idList {
		n++
		q += "$" + strconv.Itoa(n) + ","
		param = append(param, curId)
	}
	q = q[:len(q)-1]
	sqlStr := "UPDATE sys_type SET states=2, upd_time=EXTRACT(EPOCH FROM NOW()) WHERE type_id IN (" + q + ")"
	retCode, retMsg := util.CudData(sqlStr, param...)
	return &model.Result{RetCode: retCode, RetMsg: retMsg}
}

// selTypes 获取所有分类的编号
func (s *sysType) selTypes(req *sys_mod.SysTypeProReq) []*sys_mod.SysTypeSelRes {
	sqlStr := "SELECT type_id, parent_id FROM sys_type WHERE states=1 AND kind=$1 AND opt_org=$2 ORDER BY sort"
	db := util.GetDbConn()
	if rows, err := db.Query(sqlStr, req.Kind, req.OptOrg); err == nil {
		bo := &sys_mod.SysTypeSelRes{}
		var bos []*sys_mod.SysTypeSelRes
		for rows.Next() {
			err = rows.Scan(&bo.TypeId, &bo.ParentId)
			if err == nil {
				bos = append(bos, bo)
				bo = &sys_mod.SysTypeSelRes{}
			} else {
				logger.Error("分类信息封装失败。" + err.Error())
				return nil
			}
		}
		return bos
	} else {
		return nil
	}
}

// getIds 遍历获取子级模块编号
func (s *sysType) getIds(list []*sys_mod.SysTypeSelRes, id string, newList []string) []string {
	newList = append(newList, id)
	if len(list) > 0 {
		for _, item := range list {
			if id == item.ParentId {
				newList = append(newList, item.TypeId)
				newList = s.getIds(list, item.TypeId, newList)
			}
		}
	}
	return newList
}

// One 获取分类详情
func (s *sysType) One(typeId string) *model.Result {
	sqlStr := "SELECT a.type_id, a.type_name, a.type_code, a.short_name, a.full_name, a.kind, a.parent_id, a.sort, " +
		"(CASE WHEN a.parent_id='111111111111111111111' THEN '一级分类' ELSE b.type_name END) parent_name, " +
		"(CASE WHEN a.parent_id='111111111111111111111' THEN '1000' ELSE b.type_code END) parent_code, " +
		"a.logo_id, a.logo_name, a.logo_url, a.remarks, a.add_time, a.upd_time " +
		"FROM sys_type a " +
		"LEFT JOIN sys_type b ON a.parent_id=b.type_id " +
		"WHERE a.type_id=$1"
	if dbMap, err := util.GetOne(sqlStr, typeId); err == nil && len(dbMap) > 0 {
		return &model.Result{RetCode: 1001, RetMsg: "ok", RetData: dbMap}
	} else {
		return &model.Result{RetCode: 1000, RetMsg: "暂无内容"}
	}
}

// List 获取分类树状列表
func (s *sysType) List(req *sys_mod.SysTypeListReq) *model.Result {
	sqlStr := "SELECT type_id, type_name, type_code, short_name, parent_id, sort, add_time FROM sys_type a WHERE states=1 AND kind=$1 AND opt_org=$2 ORDER BY sort"
	db := util.GetDbConn()
	if rows, err := db.Query(sqlStr, req.Kind, req.OptOrg); err == nil {
		bo := &sys_mod.SysTypeListRes{}
		var bos []*sys_mod.SysTypeListRes
		for rows.Next() {
			err = rows.Scan(&bo.TypeId, &bo.TypeName, &bo.TypeCode, &bo.ShortName, &bo.ParentId, &bo.Sort, &bo.AddTime)
			if err == nil {
				bos = append(bos, bo)
				bo = &sys_mod.SysTypeListRes{}
			} else {
				logger.Error("分类信息封装失败。" + err.Error())
				return &model.Result{RetCode: 1002, RetMsg: "分类信息封装失败"}
			}
		}
		newList := make([]*sys_mod.SysTypeListRes, 0)
		if len(bos) > 0 {
			var level uint8 = 1
			for _, item := range bos {
				if "111111111111111111111" == item.ParentId {
					item.TypeLevel = level
					newList = append(newList, item)
					newList = s.sortChildType(bos, item.TypeId, newList, level)
				}
			}
		}
		return &model.Result{RetCode: 1001, RetMsg: "ok", RetData: newList}
	} else {
		return &model.Result{RetCode: 1000, RetMsg: "暂无内容"}
	}
}

// sortChildType 将分类按树状排序
func (s *sysType) sortChildType(list []*sys_mod.SysTypeListRes, typeId string, newList []*sys_mod.SysTypeListRes, level uint8) []*sys_mod.SysTypeListRes {
	level++
	for _, item := range list {
		if typeId == item.ParentId {
			item.TypeLevel = level
			newList = append(newList, item)
			newList = s.sortChildType(list, item.TypeId, newList, level)
		}
	}
	return newList
}

// Tree 获取分类树状列表
func (s *sysType) Tree(req *sys_mod.SysTypeListReq) *model.Result {
	sqlStr := "SELECT type_id sel_id, type_name sel_name, type_code sel_code, parent_id sel_pid, false chked FROM sys_type WHERE states=1 AND kind=$1 AND opt_org=$2 ORDER BY sort"
	db := util.GetDbConn()
	if rows, err := db.Query(sqlStr, req.Kind, req.OptOrg); err == nil {
		bo := &sys_mod.SysTypeTreeRes{}
		var bos []*sys_mod.SysTypeTreeRes
		for rows.Next() {
			err = rows.Scan(&bo.SelId, &bo.SelName, &bo.SelCode, &bo.SelPid, &bo.Chked)
			if err == nil {
				bos = append(bos, bo)
				bo = &sys_mod.SysTypeTreeRes{}
			} else {
				logger.Error("分类信息封装失败。" + err.Error())
				return &model.Result{RetCode: 1002, RetMsg: "分类信息封装失败"}
			}
		}
		tree := s.buildTree(bos, "111111111111111111111")
		return &model.Result{RetCode: 1001, RetMsg: "ok", RetData: tree}
	} else {
		return &model.Result{RetCode: 1000, RetMsg: "暂无内容"}
	}
}

// buildTree 创建分类的树状列表
func (s *sysType) buildTree(list []*sys_mod.SysTypeTreeRes, parentId string) []*sys_mod.SysTypeTreeRes {
	var tree []*sys_mod.SysTypeTreeRes
	if len(list) > 0 {
		for _, child := range list {
			if parentId == child.SelPid {
				tree = append(tree, s.findChild(child, list))
			}
		}
	}
	return tree
}

// findChild 分类子级分类列表数据
func (s *sysType) findChild(child *sys_mod.SysTypeTreeRes, list []*sys_mod.SysTypeTreeRes) *sys_mod.SysTypeTreeRes {
	if len(list) > 0 {
		for _, curChild := range list {
			if child.SelId == curChild.SelPid {
				child.Children = append(child.Children, s.findChild(curChild, list))
			}
		}
	}
	return child
}

// Sort 获取分类数量，用于排序
func (s *sysType) Sort(req *sys_mod.SysTypeSortReq) *model.Result {
	sqlStr := "SELECT COUNT(1)+1 AS nums FROM sys_type WHERE states=1 AND kind=$1 AND opt_org=$2 AND parent_id=$3"
	if dbMap, err := util.GetOne(sqlStr, req.Kind, req.OptOrg, req.ParentId); err == nil && len(dbMap) > 0 {
		return &model.Result{RetCode: 1001, RetMsg: "ok", RetData: dbMap["nums"]}
	} else {
		return &model.Result{RetCode: 1000, RetMsg: "暂无内容"}
	}
}

// Select 下拉选择单级分类
func (s *sysType) Select(req *sys_mod.SysTypeSelReq) *model.Result {
	sqlStr := "SELECT type_id sel_id, type_name sel_name, type_code sel_code, false chked FROM sys_type WHERE states=1 AND kind=$1 AND opt_org=$2 AND parent_id=$2 ORDER BY type_code"
	if dbMap, err := util.GetAll(sqlStr, req.Kind, req.OptOrg, req.ParentId); err == nil && len(dbMap) > 0 {
		return &model.Result{RetCode: 1001, RetMsg: "ok", RetData: dbMap}
	} else {
		return &model.Result{RetCode: 1000, RetMsg: "暂无内容"}
	}
}
